<?php
/**
 * Created by PhpStorm.
 * User: Mr.Li <lhb2002@qq.com>
 * Date: 2019/5/28
 * Time: 16:47
 */

namespace LHB_Dycdp\Gateways;

use AlibabaCloud\Client\AlibabaCloud;
use AliyunMNS\Client;
use AliyunMNS\Exception\MnsException;
use LHB_Dycdp\Exception;

class ReceiveAlicomMsg
{
    static private $instance;

    private $accessKeyId;
    private $accessKeySecret;
    private $endPoint;
    private $queueName;
    private $client;

    protected $token;

    private function __construct($accessKeyId,$accessKeySecret,$endPoint,$queueName)
    {
        $this->accessKeyId = $accessKeyId;
        $this->accessKeySecret = $accessKeySecret;
        $this->endPoint = 'http://1943695596114318.mns.cn-hangzhou.aliyuncs.com/';
        $this->queueName = "Alicom-Queue-30711001-FlowReport";
    }

    //防止克隆对象
    private function __clone(){}
    static public function getInstance($accessKeyId,$accessKeySecret,$endPoint,$queueName){
        //判断$instance是否是Uni的对象
        //没有则创建
        if (!self::$instance instanceof self) {
            self::$instance = new self($accessKeyId,$accessKeySecret,$endPoint,$queueName);
        }
        return self::$instance;

    }

    /**
     * 接收回调消息
     * @param \Closure $callback
     *              true 表示成功处理完成，会从队列中删除这条消息
     *              false 未处理成功，会重新从队列中拉取
     * @return \AliyunMNS\Responses\ReceiveMessageResponse|mixed
     * @throws Exception
     * @throws \AlibabaCloud\Client\Exception\ClientException
     * @throws \AlibabaCloud\Client\Exception\ServerException
     * User: Mr.Li <lhb2002@qq.com>
     * Date: 2019/5/29
     * Time: 9:56
     */
    public function run(\Closure $callback)
    {


        $token = $this->getToken();

        $this->client = new Client($this->endPoint, $token['AccessKeyId'], $token['AccessKeySecret'],$token['SecurityToken']);
        //$this->client = new Client($this->endPoint,$this->accessId,$this->accessKey);

        $queue = $this->client->getQueueRef($this->queueName);

        // 3. receive message
        $receiptHandle = NULL;
        try
        {
            //阻塞获取消息通知
            $res = $queue->receiveMessage(30);
            //记录日志
            file_put_contents('Receive.log',date("Y-m-d h:i:s") . " " . $res->getMessageBody() . PHP_EOL,FILE_APPEND);

            //转译消息记录
            $message = \GuzzleHttp\json_decode($res->getMessageBody(),true);

            //var_dump($message);
            //返回获取值
            $res = $callback( $message );
            if($res){
                //获取消息句柄
                $receiptHandle = $res->getReceiptHandle();
                //删除已接收的消息
                $queue->deleteMessage($receiptHandle);
            }
            return $res;

        }
        catch (MnsException $e)
        {
            throw new Exception($e->getMessage());
        }

    }


    /**
     * 获取MnsToken
     * @return mixed
     * @throws Exception
     * @throws \AlibabaCloud\Client\Exception\ClientException
     * @throws \AlibabaCloud\Client\Exception\ServerException
     * User: Mr.Li <lhb2002@qq.com>
     * Date: 2019/5/28
     * Time: 20:32
     */
    protected function getToken(){
        if($this->token == null || strtotime($this->token['ExpireTime']) - time() > 2 * 60){

            $messageType = 'FlowReport';
            AlibabaCloud::accessKeyClient($this->accessKeyId,$this->accessKeySecret)->asDefaultClient();

            try {
                $rpc = AlibabaCloud::rpc()
                            ->regionId('cn-hangzhou')
                            ->product("Dybaseapi")
                            ->version('2017-05-25')
                            ->action('QueryTokenForMnsQueue')
                            ->host("dybaseapi.aliyuncs.com")
                            ->options([
                                'query' => [
                                    'MessageType' => $messageType,
                                    'QueueName' => $this->queueName,
                                ],
                            ])
                            ->method('POST');

                $result = $rpc->request()->toArray();
                $this->token = $token = $result['MessageTokenDTO'];

                return $token;
            } catch (ClientException $exception) {
                throw new Exception("获取MnsToken失败 " . $exception->getErrorMessage());
            } catch (ServerException $exception) {
                throw new Exception("获取MnsToken失败 " . $exception->getErrorMessage());
            }
        }

        return $this->token;
    }

}